// Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
//
// Licensed under the Mulan PSL v2.
// You can use this file according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of the License at
//
//     http://license.coscl.org.cn/MulanPSL2
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
// FOR MORE DETAILS.

#include <gtest/gtest.h>

#include "DBManager/IService/Result/IResultDomainsService.h"
#include "DBManager/IService/Result/Nodal/IDISPLACEMENTService.h"

#include "../../TestDB.h"

using namespace SG::DataStructure::Post;
using namespace SG::DBManager;

TEST (O_Nodal, IDISPLACEMENTService)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取仓库服务
    auto service = DB::ServiceFactory->get<IDISPLACEMENTService> ();
    // 创建存储的数据，添加数据
    std::vector<DISPLACEMENTData> saveData;

    DISPLACEMENTData data;

    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id       = i;
        data.m_domainId = 1;
        saveData.push_back (data);
    }
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SESTATIC, 1 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    saveData.clear ();
    // 创建存储的数据，添加数据
    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id       = i;
        data.m_domainId = 2;
        saveData.push_back (data);
    }
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SESTATIC, 2 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 创建判断的数据
    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id       = i;
        data.m_domainId = 2;
        saveData.push_back (data);
    }

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result;
    ASSERT_EQ (service->Find ({ SG::DataStructure::FEM::SOLType::SOL_SESTATIC, 2 }, result),
               SG::DataStructure::Common::Status::STATUS_Success);

    // ASSERT_EQ (result.size (), 10);
    // for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    // {
    //     ASSERT_EQ (saveData[i], result[i]);
    // }

    // // 通过DomainId与实体ID获取数据，测试接口正确性
    // result.clear ();
    // ASSERT_EQ (service->Find (2, { 1 }, result), SG::DataStructure::Common::Status::STATUS_Success);
    // ASSERT_EQ (result.size (), 1);
    // ASSERT_EQ (result[0].m_id, 1);
    // ASSERT_EQ (result[0].m_domainId, 2);
}

TEST (O_Nodal, IDISPLACEMENTServiceDirectTransient)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取仓库服务
    auto service = DB::ServiceFactory->get<IDISPLACEMENTService> ();
    // 创建存储的数据，添加数据
    std::vector<DISPLACEMENTData> saveData;

    DISPLACEMENTData data;

    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id = i;
        data.m_RX = 1.0;
        data.m_RY = 2.0;
        data.m_RZ = 3.0;
        data.m_X  = 4.0;
        data.m_Y  = 5.0;
        data.m_Z  = 6.0;
        saveData.push_back (data);
    }

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 1.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 2.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 2, 1.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 2, 2.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result;
    ASSERT_EQ (service->Find ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 1.0 }, result),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (result.size (), 10);

    auto domainService = DB::ServiceFactory->get<IResultDomainsService> ();

    std::vector<ResultDomains> domainResult = domainService->GetAllData ();

    ASSERT_EQ (domainResult.size (), 4);
    ASSERT_EQ (domainResult[0].m_Subcase, 1);
    ASSERT_EQ (domainResult[0].m_TimeFrequencyEigr, 1.0);
    ASSERT_EQ (domainResult[1].m_Subcase, 1);
    ASSERT_EQ (domainResult[1].m_TimeFrequencyEigr, 2.0);
    ASSERT_EQ (domainResult[2].m_Subcase, 2);
    ASSERT_EQ (domainResult[2].m_TimeFrequencyEigr, 1.0);
    ASSERT_EQ (domainResult[3].m_Subcase, 2);
    ASSERT_EQ (domainResult[3].m_TimeFrequencyEigr, 2.0);
}

TEST (O_Nodal, IDISPLACEMENTServiceMDirectTransient)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取仓库服务
    auto service = DB::ServiceFactory->get<IDISPLACEMENTService> ();
    // 创建存储的数据，添加数据
    std::vector<DISPLACEMENTData> saveData;

    DISPLACEMENTData data;

    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id = i;
        data.m_RX = 1.0;
        data.m_RY = 2.0;
        data.m_RZ = 3.0;
        data.m_X  = 4.0;
        data.m_Y  = 5.0;
        data.m_Z  = 6.0;
        saveData.push_back (data);
    }

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEMTRAN, 1, 1.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEMTRAN, 1, 2.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEMTRAN, 2, 1.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEMTRAN, 2, 2.0 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result;
    ASSERT_EQ (service->Find ({ SG::DataStructure::FEM::SOLType::SOL_SEMTRAN, 1, 1.0 }, result),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (result.size (), 10);

    auto domainService = DB::ServiceFactory->get<IResultDomainsService> ();

    std::vector<ResultDomains> domainResult = domainService->GetAllData ();

    ASSERT_EQ (domainResult.size (), 4);
    ASSERT_EQ (domainResult[0].m_Subcase, 1);
    ASSERT_EQ (domainResult[0].m_TimeFrequencyEigr, 1.0);
    ASSERT_EQ (domainResult[1].m_Subcase, 1);
    ASSERT_EQ (domainResult[1].m_TimeFrequencyEigr, 2.0);
    ASSERT_EQ (domainResult[2].m_Subcase, 2);
    ASSERT_EQ (domainResult[2].m_TimeFrequencyEigr, 1.0);
    ASSERT_EQ (domainResult[3].m_Subcase, 2);
    ASSERT_EQ (domainResult[3].m_TimeFrequencyEigr, 2.0);
}

TEST (O_Nodal, IDISPLACEMENTServiceRepeatAdd)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取仓库服务
    auto service = DB::ServiceFactory->get<IDISPLACEMENTService> ();
    // 创建存储的数据，添加数据
    std::vector<DISPLACEMENTData> saveData;

    DISPLACEMENTData data;

    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id = i;
        data.m_RX = 1.0;
        data.m_RY = 2.0;
        data.m_RZ = 3.0;
        data.m_X  = 4.0;
        data.m_Y  = 5.0;
        data.m_Z  = 6.0;
        saveData.push_back (data);
    }

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 0.1 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 0.2 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);
    saveData.clear ();
    for (SG::DataStructure::Common::Id i = 5; i < 15; i++)
    {
        data.m_id = i;
        data.m_RX = 1.0;
        data.m_RY = 2.0;
        data.m_RZ = 3.0;
        data.m_X  = 4.0;
        data.m_Y  = 5.0;
        data.m_Z  = 6.0;
        saveData.push_back (data);
    }
    // 添加瞬态数据
    ASSERT_EQ (service->Add ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 0.3 }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result;
    ASSERT_EQ (service->Find ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 0.3 }, result),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (result.size (), 10);

    SG::DataStructure::Common::Id id = 5;
    for (DISPLACEMENTData data : result)
    {
        ASSERT_EQ (data.m_id, id);
        id++;
    }

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result2;
    ASSERT_EQ (service->Find ({ SG::DataStructure::FEM::SOLType::SOL_SEDTRAN, 1, 0.2 }, result2),
               SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (result2.size (), 10);
    id = 0;
    for (DISPLACEMENTData data : result2)
    {
        ASSERT_EQ (data.m_id, id);
        id++;
    }
}

TEST (O_Nodal, IDISPLACEMENTServiceRandom)
{
    DB::ServiceFactory->ClearDatabase ();
    // 获取仓库服务
    auto service = DB::ServiceFactory->get<IDISPLACEMENTService> ();
    // 创建存储的数据，添加数据
    std::vector<DISPLACEMENTData> saveData;

    DISPLACEMENTData data;

    for (SG::DataStructure::Common::Id i = 0; i < 10; i++)
    {
        data.m_id = i;
        data.m_RX = 1.0;
        data.m_RY = 2.0;
        data.m_RZ = 3.0;
        data.m_X  = 4.0;
        data.m_Y  = 5.0;
        data.m_Z  = 6.0;
        saveData.push_back (data);
    }

    ASSERT_EQ (service->Add ({ 999, 0.1, SG::DBManager::Post::DomainRequest::RandomResultType::PSD }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (service->Add ({ 999, 0.2, SG::DBManager::Post::DomainRequest::RandomResultType::PSD }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (service->Add ({ 999, 0.1, SG::DBManager::Post::DomainRequest::RandomResultType::AVGSUM }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (service->Add ({ 999, 0.2, SG::DBManager::Post::DomainRequest::RandomResultType::AVGSUM }, saveData),
               SG::DataStructure::Common::Status::STATUS_Success);

    // 通过DomainId获取数据，测试接口正确性
    std::vector<DISPLACEMENTData> result;
    ASSERT_EQ (service->Find ({ 999, 0.2, SG::DBManager::Post::DomainRequest::RandomResultType::AVGSUM }, result),
               SG::DataStructure::Common::Status::STATUS_Success);

    ASSERT_EQ (result.size (), 10);

    SG::DataStructure::Common::Id id = 0;
    for (const auto& data : result)
    {
        ASSERT_EQ (data.m_id, id);
        id++;
    }

    // 通过DomainId获取数据，测试接口正确性
    ASSERT_EQ (service->Find ({ 999, 0.1, SG::DBManager::Post::DomainRequest::RandomResultType::PSD }, result),
               SG::DataStructure::Common::Status::STATUS_Success);
    ASSERT_EQ (result.size (), 10);
    id = 0;
    for (const auto& data : result)
    {
        ASSERT_EQ (data.m_id, id);
        id++;
    }
}
